#pragma once
/*
	文件版本
*/
#include <iostream>
#include <string>
#include <unordered_map>
#include <vector>
#include <assert.h>
#include <fstream>
#include <mysql/mysql.h>

#include "../comm/log.hpp"
#include "../comm/util.hpp"

namespace ns_model
{
	using namespace std;
	using namespace ns_log;
	using namespace ns_util;

	//题目信息
	struct Question
	{
		std::string number;	//题目编号，唯一
		std::string title;	//题目的标题
		std::string star;	//难度: 简单 中等 困难
		int cpu_limit;		//题目的时间要求(S)
		int mem_limit;		//题目的空间要去(KB)
		std::string  desc;	//题目的描述
		std::string header;	//题目预设给用户在线编辑器的代码
		std::string tail;	//题目的测试用例，需要和header拼接，形成完整代码
	};

	const std::string host = "127.0.0.1";
	const int port = 3306;
	const std::string user = "oj_server";
	const std::string db = "oj_server";
	const string passwd = "123456";
	const std::string questions = "questions";

	class Model
	{
		private:
		std::unordered_map<std::string,Question> _QuestionList;

		public:
		Model()
		{}
		~Model(){}

		//mysql加载题目
		//sql	 sql语句
		//out	 获取到的题目列表
		bool QueryMysql(const string& sql,vector<Question>* out)
		{
			//初始化
			MYSQL *mysql = mysql_init(nullptr);
			// LOG(DEBUG) << "初始化" << endl;

			//连接数据库
			if(nullptr == mysql_real_connect(mysql,host.c_str(),user.c_str(),passwd.c_str(),db.c_str(),port,nullptr,0))
			{
				LOG(FATAL) << "连接数据库失败!" << "\n";
				return false;
			}
			// LOG(DEBUG) << "连接数据库!" << endl;

			// 一定要设置该链接的编码格式, 要不然会出现乱码问题
			mysql_set_character_set(mysql,"utf8");
			// LOG(DEBUG) << "编码格式!" << endl;

			// 执行sql语句
			if(0 != mysql_query(mysql,sql.c_str()))
			{
				LOG(ERROR) << sql << " execute error!" << "\n";
				return false;
			}
			// LOG(DEBUG) << "执行sql语句!" << endl;

			// 提取结果
			MYSQL_RES *res = mysql_store_result(mysql);
			// LOG(DEBUG) << "提取结果" << endl;

			// 分析结果
			int rows = mysql_num_rows(res);	//获取行数
			// int cols = mysql_num_fields(res);	//获取列数
			// LOG(DEBUG) << "分析结果" << endl;

			Question q;
			for(int i = 0; i < rows;i++)
			{
				MYSQL_ROW line = mysql_fetch_row(res);
				q.number = line[0];
				q.title = line[1];
				q.star = line[2];
				q.desc = line[3];
				q.header = line[4];
				q.tail = line[5];
				q.cpu_limit = atoi(line[6]);
				q.mem_limit = atoi(line[7]);

				out->push_back(q);
			}

			//释放结果空间
			// free(res);		//5.7版本之前需要自己释放，新版本不需要了，内部会自己释放
			// LOG(DEBUG) << "释放结果空间" << endl;
			//关闭mysql连接
			mysql_close(mysql);
			// LOG(DEBUG) << "关闭mysql连接" << endl;
			return true;
		}

		//获取所有题目
		bool GetAllQuestions(vector<Question> *out)
		{
			string sql = "select * from ";
			sql += questions;
			return QueryMysql(sql,out);
		}

		//获取单个题目
		bool GetOneQuestion(const std::string &number, Question *q)
		{
			bool res = false;
			string sql = "select * from ";
			sql += questions;
			sql += " ";
			sql += "where id = ";
			sql += number;
			vector<Question> result;
			if(QueryMysql(sql,&result))
			{
				if(result.size() == 1)
				{
					*q = result[0];
					res = true;
				}
			}
			return res;
		}
	};
}
